package comparisons

import (
	"hi-jvm/instructions/base"
	"hi-jvm/rtda"
)

// Branch if int comparison with zero succeeds
// 如果与零的int比较成功，则执行分支
// 把栈顶的int变量弹出，然后与0进行比较，满足条件则跳转
type IFEQ struct{ base.BranchInstruction }
type IFNE struct{ base.BranchInstruction }
type IFLT struct{ base.BranchInstruction }
type IFLE struct{ base.BranchInstruction }
type IFGT struct{ base.BranchInstruction }
type IFGE struct{ base.BranchInstruction }

func (self *IFEQ) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val == 0
	})
}

func (self *IFNE) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val != 0
	})
}

func (self *IFLT) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val < 0
	})
}

func (self *IFLE) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val <= 0
	})
}

func (self *IFGT) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val > 0
	})
}

func (self *IFGE) Execute(frame *rtda.Frame) {
	executeInIfCond(frame, self.Offset, func(val int32) bool {
		return val >= 0
	})
}

func executeInIfCond(frame *rtda.Frame, offset int,  cond func(int32) bool) {
	val := frame.OperandStack.PopInt()
	if cond(val) {
		base.Branch(frame, offset)
	}
}